package dryven.view.engine.expression.nodetypes;

import dryven.codegen.asm.MethodBuilder;
import dryven.codegen.asm.TempValue;
import dryven.reflection.Method;
import dryven.reflection.MethodIterator;
import dryven.reflection.MethodListener;
import dryven.reflection.TypeRef;
import dryven.reflection.LiteralTypeRef;
import dryven.view.engine.expression.Evaluator;
import dryven.view.engine.expression.ExpressionNode;
import dryven.view.engine.expression.nodelisters.NodeLister;
import dryven.view.engine.expression.nodelisters.ExpressionNodeFactory;

public class MethodCallNode extends AbstractExpressionNode {

	private String _name;
	private Method _method;
	
	public MethodCallNode(String name, Method m, NodeLister lister) {
		super(lister);
		this._name = name;
		_method = m;
	}

	@Override
	public TypeRef getComponentType() {
		return null;
	}
	
	@Override
	public Iterable<ExpressionNode> getChildren() {
		
		return super.getChildren();
	}

	@Override
	public String getName() {
		return _name;
	}

	@Override
	public TypeRef getType() {
		return _method.getReturnType();
	}

	@Override
	public Object evaluate(Object value) {
		Class<?> clazz = _method.getDeclaringType().getTypeClass();
		int paramLength = _method.getParameterType()==null?0:_method.getParameterType().length;
		Class<?> paramTypes[] = new Class<?>[paramLength];
		if(paramLength!=0) {
			for(int i=0;i<paramLength;++i) {
				paramTypes[i]=_method.getParameterType()[i].getTypeClass();
			}
		}
		try {
			java.lang.reflect.Method m = clazz.getMethod(_method.getName(), paramTypes);
			//TODO change this if we are ever to allow method calls with parameters
			Object newValue = m.invoke(value, new Object[]{});
			return newValue;
		} catch (Exception e) {
			throw new RuntimeException(String.format("Could not invoke method %s.%s",_method.getReturnType().getTypeName(),_method.getName()),e);
		}
		
	}

	@Override
	public TempValue writeInstructions(MethodBuilder builder, TempValue value) {
		// TODO Auto-generated method stub
		return null;
	}

}